package com.cw.jeeyt.common.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cw.lang.common.utils.CollectionUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * maven工具类
 *
 * @author chenw
 * @version 1.0.0
 */
@Slf4j
public class MavenUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(MavenUtil.class);
    //MavenUtil.class.getClassLoader().getResource("../").getPath();
    private final static String WEB_INF_PATH = "./";
    private final static String COMPILE_PATH = WEB_INF_PATH + "sourceCode/";
    private final static String EMBEDDED_MAVEN_PATH = WEB_INF_PATH + "maven/";
    private final static List<String> fileList = new ArrayList<String>();

    public static void main(String[] args) {
        new MavenUtil().maven("D:/chenw_project/git_compile/","jeeyt","dev1.1");
    }

    public void maven(String path,String projectCode,String newBranchCode) {
        List<String> getPoms = findPomFile(path + projectCode);
        replaceVersion(getPoms,newBranchCode);
        boolean flag = isJacoco(getPoms);
        List<String> fileList = getModuleList(getPoms);
        for (String pom : fileList) {
            ProcessBuilder pb = new ProcessBuilder();
            //构建命令
            if (System.getProperty("os.name")
                .contains("Windows")) {
                if (flag) {
                    pb.command("cmd", "/c", "mvn", "clean", "test", "compile", "-f", pom);
                } else {
                    pb.command("cmd", "/c", "mvn", "-DskipTests=true", "clean", "compile", "-f", pom);
                }

            } else if (System.getProperty("os.name")
                .contains("Linux")) {
                if (flag) {
                    pb.command("mvn", "clean", "test", "compile", "-f", pom);
                } else {
                    pb.command("mvn", "-DskipTests=true", "clean", "compile", "-f", pom);
                }
            } else {
                LOGGER.info("Unknown System..." + System.getProperty("os.name"));
            }
            try {
                //执行命令
                Process process = pb.start();
                InputStream inputStream = process.getInputStream();
                byte[] buffer = new byte[1024];
                int readSize;
                while ((readSize = inputStream.read(buffer)) > 0) {
                    System.out.write(buffer, 0, readSize);
                }
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }

    /**
     * 查找所有pom文件
     *
     * @param path
     * @return
     */
    private static List<String> findPomFile(String path) {
        File file = new File(path);

        if (file.exists()) {
            File[] files = file.listFiles();
            if (null == files || files.length == 0) {
                log.info("文件夹是空的!");
                return fileList;
            } else {
                for (File file2 : files) {
                    if (file2.isDirectory() && !file2.getName()
                        .contains(".git") && !file2.getName()
                        .contains("src")) {
                        // 此处是文件夹
                        findPomFile(file2.getAbsolutePath());
                    } else {
                        if (file2.getName()
                            .contains("pom.xml")) {
                            fileList.add(file2.getAbsolutePath());
                            log.info("文件:" + file2.getAbsolutePath());
                        }
                    }
                }
            }
        } else {
            log.info("文件不存在!");
        }
        return fileList;
    }

    /**
     * 判断是否存在多模块，如果存在将会去除存在模块的pom文件
     *
     * @param fromPoms
     * @return
     */
    private static List<String> getModuleList(List<String> fromPoms) {
        int count = fromPoms.size();
        for (String getPom : fromPoms) {
            final SAXReader reader = new SAXReader();
            Document document;
            try {
                document = reader.read(getPom);
                final List modules = document.getRootElement()
                    .element("modules")
                    .elements();
                if (modules != null) {
                    for (final Object module : modules) {
                        final String moduleName = ((Element) module).getText();
                        Iterator<String> iterator = fromPoms.iterator();
                        while (iterator.hasNext()) {
                            String pom = iterator.next();
                            if (pom.contains(moduleName)) {
                                iterator.remove();
                                count--;
                            }
                        }
                    }
                }
                if (count <= 1) {
                    break;
                }
            } catch (final DocumentException e) {
                e.printStackTrace();
            } catch (NullPointerException e) {
                log.info(getPom);
            }
        }
        return fromPoms;
    }
    /**
     * 更换版本
     *
     * @param fromPoms
     * @return
     */
    private static List<String> replaceVersion(List<String> fromPoms,String newBranchCode) {
        for (String getPom : fromPoms) {
            if(getPom.equals("D:\\chenw_project\\git_compile\\jeeyt\\pom.xml")){
                log.info(getPom);
            }
            XMLWriter writer = null;
            final SAXReader reader = new SAXReader();
            Document document;
            try {
                document = reader.read(getPom);
                Element parentElement = document.getRootElement()
                    .element("parent");
                List<Element> elements = null;
                if(parentElement != null){
                   elements = parentElement.elements();
                }
                if (CollectionUtil.isNotEmpty(elements)) {
                    for (Element element : elements) {
                        String moduleName = element.getName();
                        if("version".equals(moduleName)){
                            element.setText(newBranchCode);
                        }
                    }
                }
                final Element verElement = document.getRootElement().element("version");
                if(verElement != null){
                    if("version".equals(verElement.getName())){
                        verElement.setText(newBranchCode);
                    }
                }
                writer = new XMLWriter(new FileWriter(new File(getPom)));
                writer.write(document);
            } catch (final DocumentException e) {
                e.printStackTrace();
            } catch (NullPointerException e) {
                log.info(getPom);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(writer != null){
                    try {
                        writer.flush();
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return fromPoms;
    }
    /**
     * 读取文件，判断读取的行中是否存在jacoco字符串
     *
     * @param poms
     * @return
     */
    private static boolean isJacoco(List<String> poms) {
        boolean flag = false;
        BufferedReader reader = null;
        try {
            for (String getPom : poms) {
                File pomFile = new File(getPom);
                reader = new BufferedReader(new FileReader(pomFile));
                String tempString = null;
                while ((tempString = reader.readLine()) != null) {
                    if (tempString.contains("org.jacoco")) {
                        flag = true;
                        break;
                    }
                }
                reader.close();
                if (flag) {
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        return flag;
    }

    /**
     * 修改权限（这里粗犷的修改为777，如有精细化的权限控制，自己调整一下）
     * 因为一些原因，虽然线上默认的执行用户是root，并且权限为rwx，依然会报权限不足的错误
     * 如果有大神指导原因请指点一二
     *
     * @throws Exception
     */
    public void afterPropertiesSet() throws Exception {
        //修改maven目录权限
        Process chmodMaven = new ProcessBuilder("chmod", "-R", "777", EMBEDDED_MAVEN_PATH).start();
        //等待完成
        chmodMaven.waitFor();
        LOGGER.info("修改权限完成：{}", EMBEDDED_MAVEN_PATH);

        //修改编译目录权限
        Process chmodCompile = new ProcessBuilder("chmod", "-R", "777", COMPILE_PATH).start();
        chmodCompile.waitFor();
        LOGGER.info("修改权限完成：{}", COMPILE_PATH);
    }

    /**
     * 递归查找文件
     *
     * @param baseDirName 查找的文件夹路径
     * @param targetFileName 需要查找的文件名
     */
    public static List<File> findFiles(String baseDirName, String targetFileName) {
        List<File> fileList = new ArrayList<>();

        // 创建一个File对象
        File baseDir = new File(baseDirName);
        // 判断目录是否存在
        if (!baseDir.exists() || !baseDir.isDirectory()) {
            log.info("文件查找失败：" + baseDirName + "不是一个目录！");
        }
        String tempName;

        File tempFile;
        File[] files = baseDir.listFiles();
        //该文件夹下没有文件，为空文件夹
        if (files.length == 0) {
            log.info("为空文件夹");
        }
        for (int i = 0; i < files.length; i++) {
            tempFile = files[i];
            if (tempFile.isDirectory()) {
                findFiles(tempFile.getAbsolutePath(), targetFileName);
            } else if (tempFile.isFile()) {
                tempName = tempFile.getName();
                if (tempName.equals(targetFileName)) {
                    log.info(tempFile.getAbsoluteFile()
                        .toString());
                    fileList.add(tempFile.getAbsoluteFile());
                }
            }
        }
        return fileList;
    }
}
